home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume6 / unrm.rm < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  10.2 KB

  1. Subject: v06i025:  "rm" and "unrm" programs (unrm.rm)
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: Dave Taylor <pyramid!hplabs!hpldat!taylor>
  6. Mod.sources: Volume 6, Issue 25
  7. Archive-name: unrm.rm
  8.  
  9. [  I wrote a brief manpage and a Makefile; I hope Dave forgives
  10.    the (humorous) editorial comment in the latter.  Some sites
  11.    will want to change the "LOGNAME" strings to "USER" or similar,
  12.    in the code below.  --r$]
  13.  
  14. The following `shar' file contains two programs that, when installed, will
  15. allow you to use "rm" as usual but also have the ability to change your
  16. mind and use "unrm".  
  17.  
  18.             Another useful program from....
  19.  
  20.                         -- Dave Taylor
  21.  
  22.     taylor/HP1900/UX,   taylor@HPLABS.{CSNET, ARPA}  or  ..hplabs!taylor
  23.  
  24.  
  25. --------------------CUT HERE--------------------
  26. #!/bin/sh
  27. # This is a shell archive.  Remove anything before this line,
  28. # then unpack it by saving it in a file and typing "sh file".
  29. # Contents:  rm.c unrm.1 unrm.c Makefile
  30.  
  31. echo x - rm.c
  32. sed 's/^XX//' > "rm.c" <<'@//E*O*F rm.c//'
  33. XX/**            rm.c            **/
  34.  
  35. XX/** This program replaces 'rm' (it's assumed that this program is BEFORE 
  36. XX    /bin/rm in the path) and will ferret away copies of the files being 
  37. XX    removed to the directory /tmp/rm/<login>.  Files that are copied into 
  38. XX    /tmp/rm/* can be recalled by 'unrm filename'.  Every so often (probably 
  39. XX    midnight every night) a daemon should clear out the old files in the
  40. XX    /tmp/rm directory...
  41.  
  42. XX    (C) Copyright 1986, Dave Taylor, Hewlett-Packard Company
  43. XX**/
  44.  
  45. XX#include <stdio.h>
  46. XX#include <errno.h>
  47.  
  48. XX#define  real_rm    "/bin/rm"
  49. XX#define  RM_DIR        "/tmp/rm"
  50.  
  51. XX#define  ACCESS_MODE    04 & 02
  52. XX#define  DIR_ACCESS    04 & 01
  53.  
  54. XX#define  SLEN        80
  55.  
  56. XX#define  USERS_NAME    "LOGNAME"        /* "USER" in BSD */
  57.  
  58. XXextern int errno;
  59.  
  60. XXchar *basename(), *getlogin(), *getenv();
  61.  
  62. XXmain(argc, argv)
  63. XXint argc;
  64. XXchar **argv;
  65. XX{
  66. XX    extern int optind;    /* for getopt */
  67. XX    char   buffer[SLEN], login_name[SLEN], dirname[SLEN], *cp;
  68. XX    int    c, oldumask; 
  69.  
  70. XX    while ((c = getopt(argc, argv, "rfi")) != EOF) {
  71. XX      switch (c) {
  72. XX        case 'r' : 
  73. XX        case 'f' : 
  74. XX        case 'i' : break;    /* just accept 'em... */
  75. XX        case '?' : exit(fprintf(stderr,"Usage: rm [-rfi] files\n"));
  76. XX      }
  77. XX    }
  78.  
  79. XX    if (strlen(argv[optind]) == 0)
  80. XX      exit(0);
  81.  
  82. XX    /* is the top level /tmp directory available??? */
  83.  
  84. XX    if (access(RM_DIR, DIR_ACCESS)) {
  85. XX      sprintf(buffer,"mkdir %s; chmod 777 %s", RM_DIR, RM_DIR);
  86. XX      if (system(buffer) != 0) {
  87. XX        printf("'%s' failed!!\n", buffer);
  88. XX        exit(1);
  89. XX      }
  90. XX    }
  91.  
  92. XX    /* now get the users login name... */
  93.  
  94. XX    if ((cp = getenv(USERS_NAME)) == NULL)
  95. XX      strcpy(login_name, getlogin());
  96. XX    else
  97. XX      strcpy(login_name, cp);
  98.  
  99. XX    /* let's see if THAT directory is hangin' around... */
  100.  
  101. XX    sprintf(dirname, "%s/%s", RM_DIR, login_name);
  102.  
  103. XX    if (access(dirname, DIR_ACCESS)) {
  104. XX      sprintf(buffer,"mkdir %s; chmod 700 %s", dirname, dirname);
  105. XX      if (system(buffer) != 0) {
  106. XX        printf("'%s' failed!!\n", buffer);
  107. XX        exit(1);
  108. XX      }
  109. XX    }
  110.  
  111. XX    oldumask = umask(077);
  112. XX    while (strlen(argv[optind]) > 0) {
  113. XX      if (access(basename(argv[optind]), ACCESS_MODE) == 0)
  114. XX        save_copy_of(dirname, argv[optind]);
  115. XX      optind++;
  116. XX    }
  117. XX    (void) umask(oldumask);
  118.  
  119. XX    execv(real_rm, argv);
  120. XX    
  121. XX    fprintf(stderr,"rm: error %d exec'ing!\n", errno);
  122. XX}
  123.  
  124. XXchar *basename(string)
  125. XXchar *string;
  126. XX{
  127. XX    /** returns the basename of the file specified in string **/
  128.  
  129. XX    static   char *buff;
  130.  
  131. XX    buff = string + strlen(string); /* start at last char */
  132. XX    
  133. XX    while (*buff != '/' && buff > string) buff--;
  134.  
  135. XX    return( (char *) (*buff == '/'? ++buff : buff));
  136. XX}
  137.  
  138. XXsave_copy_of(dirname, filename)
  139. XXchar *dirname, *filename;
  140. XX{
  141. XX    /** Try to link filename to dirname, if that fails, copy it
  142. XX        bit by bit... **/
  143.  
  144. XX    char newfname[80];
  145.  
  146. XX    sprintf(newfname,"%s/%s", dirname, basename(filename));
  147.  
  148. XX    (void) unlink(newfname);    /* blow it away if already there! */
  149.  
  150. XX    if (link(filename, newfname) != 0) {
  151. XX      FILE *infile, *outfile;    
  152. XX      int   c;
  153. XX      
  154. XX      if ((infile = fopen(filename, "r")) == NULL)
  155. XX        exit(fprintf(stderr, "rm: can't read file '%s' to save a copy!\n", 
  156. XX         filename));
  157.  
  158. XX      if ((outfile = fopen(newfname, "w")) == NULL)
  159. XX        exit(fprintf(stderr, "rm: can't write to file '%s'!\n",
  160. XX         newfname));
  161.  
  162. XX      while ((c = getc(infile)) != EOF)
  163. XX        putc(c, outfile);
  164. XX      
  165. XX      fclose(infile);
  166. XX      fclose(outfile);
  167. XX    }
  168. XX}
  169. @//E*O*F rm.c//
  170. chmod u=rw,g=r,o=r rm.c
  171.  
  172. echo x - unrm.1
  173. sed 's/^XX//' > "unrm.1" <<'@//E*O*F unrm.1//'
  174. XX.TH UNRM 1 LOCAL
  175. XX.SH NAME
  176. XXunrm, rm \- remove files and bring them back
  177. XX.SH SYNOPSIS
  178. XX.B unrm
  179. XX[
  180. XX.B \-f
  181. XX] file ...
  182. XX.br
  183. XX.B rm
  184. XXfile ...
  185. XX.SH DESCRIPTION
  186. XX.I Rm
  187. XXis a local replacement for the standard
  188. XX.IR rm (1)
  189. XXcommand.  Prior to removing a file it ferrets away a copy of it in
  190. XXthe directory
  191. XX.RI /tmp/rm/ login_id ,
  192. XXcreating each component along the way as necessary.
  193. XXThe standard ``\-r,'' ``\-f,'' and ``\-i'' options may be specified,
  194. XXbut they are ignored.
  195. XX.PP
  196. XXFiles that have been deleted with this version of
  197. XX.I rm
  198. XXcan than be retrieved with the
  199. XX.I unrm
  200. XXcommand.
  201. XX.I Unrm
  202. XXchecks to see that you are indeed the owner of a file before you
  203. XXcan copy it.  It will not overwrite a file of the same name in the
  204. XXcurrent directory, unless the ``\-f'' flag is specified, which
  205. XXcauses the file to be replaced regardless.
  206. XX.PP
  207. XXIf these programs are available, the system administror will probably want
  208. XXto add a line like the following to /usr/lib/crontab:
  209. XX.RS
  210. XX40 4 * * *      find /tmp -mtime +2 -exec rm -f {} ;
  211. XX.RE
  212. XXThis removes all files from temp that haven't been touched within
  213. XXtwo days.
  214. XX.SH BUGS
  215. XXStrange things can happen if you try to specify something other than
  216. XXa regular file.
  217. @//E*O*F unrm.1//
  218. chmod u=rw,g=rw,o=rw unrm.1
  219.  
  220. echo x - unrm.c
  221. sed 's/^XX//' > "unrm.c" <<'@//E*O*F unrm.c//'
  222. XX/**            unrm.c            **/
  223.  
  224. XX/** This is the companion program to the rm.c program, and will extract
  225. XX    files from the RM_DIR/login directory if they exist.  It checks to see 
  226. XX    that you are indeed the owner of the file before it'll let you copy
  227. XX    it AND it ensures that the file doesn't already exist in the current
  228. XX    directory (makes sense, eh?).
  229.  
  230. XX    This will not allow unrm'ing files that aren't owned by you, nor 
  231. XX    will it allow restores that replace a file of the same name in the
  232. XX    current directory (unless '-f' is specified, which will cause the
  233. XX    file to be replaced regardless).
  234.  
  235. XX    (C) Copyright 1986, Dave Taylor, Hewlett-Packard
  236. XX**/
  237.  
  238. XX#include <stdio.h>
  239. XX#include <errno.h>
  240. XX#include <sys/types.h>
  241. XX#include <sys/stat.h>
  242.  
  243. XX#define  RM_DIR        "/tmp/rm"
  244.  
  245. XX/** access modes for calls to 'access()' **/
  246.  
  247. XX#define  DIRACCESS    02 & 04
  248. XX#define  TOCOPY        04
  249. XX#define  TOREPLACE    02 & 04
  250.  
  251. XX#define  SLEN        80
  252.  
  253. XXint      force_overwrite = 0;        /* replace current regardless! */
  254.  
  255. XXchar     *getenv(), *getlogin();
  256.  
  257. XXmain(argc, argv)
  258. XXint argc;
  259. XXchar **argv;
  260. XX{
  261. XX    extern int optind;    /* for getopt */
  262. XX    char   buffer[SLEN], login_name[SLEN], dirname[SLEN], *cp;
  263. XX    int    c;
  264.  
  265. XX    while ((c = getopt(argc, argv, "f")) != EOF) {
  266. XX      switch (c) {
  267. XX        case 'f' : force_overwrite++;    break;
  268. XX        case '?' : exit(fprintf(stderr,"Usage: unrm [-f] files\n"));
  269. XX      }
  270. XX    }
  271.  
  272. XX    if (argv[optind] == 0 || strlen(argv[optind]) == 0)
  273. XX      exit(0);
  274.  
  275. XX    if (access(RM_DIR, DIRACCESS)) {
  276. XX      fprintf(stderr,"Error: Directory %s doesn't exist!\n", RM_DIR);
  277. XX      exit(0);
  278. XX    }
  279.  
  280. XX    if ((cp = getenv("LOGNAME")) == NULL)
  281. XX      strcpy(login_name, getlogin());
  282. XX    else
  283. XX      strcpy(login_name, cp);
  284.  
  285. XX    sprintf(dirname, "%s/%s", RM_DIR, login_name);
  286.  
  287. XX    if (access(dirname, DIRACCESS)) {
  288. XX      fprintf(stderr,"Error: Directory %s doesn't exist!\n", dirname);
  289. XX      exit(0);
  290. XX    }
  291.  
  292.  
  293. XX    while (argv[optind] && strlen(argv[optind]) > 0) {
  294. XX      restore(dirname, argv[optind]);
  295. XX      optind++;
  296. XX    }
  297.  
  298. XX    exit(0);
  299. XX}
  300.  
  301. XXrestore(directory, filename)
  302. XXchar *directory, *filename;
  303. XX{
  304. XX    /** Try to link RM_DIR/filename to current directory.  If that
  305. XX        fails, try to copy it byte by byte... **/
  306.  
  307. XX    struct stat buffer;
  308. XX    char newfname[80], answer[80];
  309.  
  310. XX    sprintf(newfname,"%s/%s", directory, filename);
  311.  
  312. XX    if (access(newfname,TOCOPY) != 0)
  313. XX      return(fprintf(stderr,"Error: Can't find old copy of '%s'!\n", 
  314. XX         filename));
  315. XX    
  316. XX    if (stat(newfname, &buffer) != 0)
  317. XX      return(fprintf(stderr,"Error: Can't stat old copy of '%s'!\n", 
  318. XX         filename));
  319.  
  320. XX    if (buffer.st_uid != getuid())
  321. XX      return(fprintf(stderr,"Error: File '%s' isn't yours to restore!\n", 
  322. XX         filename));
  323.  
  324. XX    /** now we're ready to start some REAL work... **/
  325.  
  326. XX    if (access(filename,TOREPLACE) == 0) {    /* it exists! */
  327. XX      if (! force_overwrite)
  328. XX        printf(
  329. XX        "File %s already exists in this directory!  Replace it? (y/n) ",
  330. XX               filename);
  331. XX        gets(answer, 1);
  332. XX        if (tolower(answer[0]) != 'y') {
  333. XX          fprintf(stderr,"Restore of file %s cancelled\n", filename);
  334. XX          return;
  335. XX        }
  336. XX    }
  337.  
  338. XX    (void) unlink(filename);    /* blow it away, if it's here! */
  339.  
  340. XX    if (link(newfname, filename) != 0) {
  341. XX      FILE *infile, *outfile;    
  342. XX      int   c;
  343. XX      
  344. XX      if ((infile = fopen(newfname, "r")) == NULL)
  345. XX        exit(fprintf(stderr, 
  346. XX                 "Error: Can't read file '%s' to restore from!\n", 
  347. XX         newfname));
  348.  
  349. XX      if ((outfile = fopen(filename, "w")) == NULL)
  350. XX        exit(fprintf(stderr, "Error: Can't write to file '%s'!\n",
  351. XX         filename));
  352.  
  353. XX      while ((c = getc(infile)) != EOF)
  354. XX        putc(c, outfile);
  355. XX      
  356. XX      fclose(infile);
  357. XX      fclose(outfile);
  358. XX    }
  359.  
  360. XX    unlink(newfname);
  361.  
  362. XX    fprintf(stderr,"Restored file '%s'\n", filename);
  363. XX}
  364. @//E*O*F unrm.c//
  365. chmod u=rw,g=r,o=r unrm.c
  366.  
  367. echo x - Makefile
  368. sed 's/^XX//' > "Makefile" <<'@//E*O*F Makefile//'
  369.  
  370. XXall:    unrm rm
  371.  
  372. XXunrm:    unrm.c    ;    cc $(CFLAGS) -o $@ $?
  373. XXrm:    rm.c    ;    cc $(CFLAGS) -o $@ $?
  374. XXinstall:
  375. XX    @echo surely you jest
  376. @//E*O*F Makefile//
  377. chmod u=rw,g=rw,o=rw Makefile
  378.  
  379. echo Inspecting for damage in transit...
  380. temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
  381. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  382. cat > $temp <<\!!!
  383.      136     428    3194 rm.c
  384.       43     221    1170 unrm.1
  385.      142     454    3554 unrm.c
  386.        7      24     117 Makefile
  387.      328    1127    8035 total
  388. !!!
  389. wc  rm.c unrm.1 unrm.c Makefile | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  390. if test -s $dtemp
  391. then echo "Ouch [diff of wc output]:" ; cat $dtemp
  392. else echo "No problems found."
  393. fi
  394. exit 0
  395.